package com.youlu.campus.service.qa.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.entity.*;
import com.youlu.campus.entity.VO.req.*;
import com.youlu.campus.entity.english.UserQuestionInfo;
import com.youlu.campus.entity.english.vo.response.UserQaInfoResponse;
import com.youlu.campus.service.activity.ActivityService;
import com.youlu.campus.service.activity.UserParticipateActivityInfoService;
import com.youlu.campus.service.course.UserActivityService;
import com.youlu.campus.service.english.CompetitionQaInfoService;
import com.youlu.campus.service.qa.ActivityQaInfoService;
import com.youlu.campus.service.qa.ActivityQaRuleService;
import com.youlu.campus.service.qa.UserQaInfoService;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import lombok.extern.slf4j.Slf4j;
import ma.glasnost.orika.MapperFacade;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.repository.support.PageableExecutionUtils;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.validation.constraints.NotBlank;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class ActivityQaInfoServiceImpl implements ActivityQaInfoService {
    @Autowired
    private MongoTemplate mongoTemplate;
    @Lazy
    @Autowired
    private ActivityService activityService;

    @Autowired
    private CompetitionQaInfoService competitionQaInfoService;
    @Lazy
    @Autowired
    private UserQaInfoService userQaInfoService;

    @Autowired
    private ActivityQaRuleService activityQaRuleService;

    @Autowired
    private MapperFacade mapperFacade;
    @Lazy
    @Autowired
    private UserParticipateActivityInfoService userParticipateActivityInfoService;
    @Lazy
    @Autowired
    private UserActivityService userActivityService;

    @Override
    public void questionImport(String userId, String activityQaInfoId, List<QaQuestionImportVO> qaQuestionImportList) {
        log.info("当前用户->{}正在导入题库 - > {}", userId, activityQaInfoId);
        long count = qaQuestionImportList.stream().map(qaQuestionImport -> qaQuestionImport.getQaQuestionNumber()).distinct().count();
        if (qaQuestionImportList.size() > count) {
            log.error("题编号 - > {} 存在重复", activityQaInfoId);
            throw new BusinessException("题编号存在重复");
        }
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(activityQaInfoId, ActivityQaInfo.class);
        if (Objects.isNull(activityQaInfo)) {
            log.error("活动题库不存在 - > {} ", activityQaInfoId);
            throw new BusinessException("题库问题不存在");
        }
        qaQuestionImportList.stream().forEach(qaQuestionImport -> {
            checkQaQuestion(activityQaInfoId, qaQuestionImport);
            Query query = new Query();
            query.addCriteria(Criteria.where("activityQaInfoId").is(activityQaInfoId));
            query.addCriteria(Criteria.where("priority").is(qaQuestionImport.getQaQuestionNumber()));
            ActivityQuestionInfo questionInfo = this.mongoTemplate.findOne(query, ActivityQuestionInfo.class);
            if (Objects.isNull(questionInfo)) {
                questionInfo = new ActivityQuestionInfo();
                questionInfo.setId(new ObjectId().toString());
                questionInfo.setCreatedTime(new Date());
            }
            questionInfo.setActivityQaInfoId(activityQaInfoId);
            questionInfo.setPriority(qaQuestionImport.getQaQuestionNumber());
            questionInfo.setScore(qaQuestionImport.getScore());
            questionInfo.setTitle(qaQuestionImport.getTitle());
            questionInfo.setQaAnalysis(qaQuestionImport.getQaAnalysis());
            List<ActivityAnswerInfo> answerInfos = new ArrayList<>();
            answerInfos.addAll(buildImportQaQuestionAnswer(activityQaInfo.getActivityId(), activityQaInfoId, qaQuestionImport));
            if (qaQuestionImport.getType() == 1) {
                questionInfo.setType(1);
            } else {
                questionInfo.setType(0);
            }
            Integer[] index = {1};
            ActivityQuestionInfo finalQuestionInfo = questionInfo;
            answerInfos.stream().peek(activityAnswerInfo -> {
                activityAnswerInfo.setPriority(index[0]++);
                activityAnswerInfo.setActivityQuestionId(finalQuestionInfo.getId());
            }).collect(Collectors.toList());
            questionInfo.setAnswerInfos(answerInfos);
            this.mongoTemplate.save(questionInfo);
            query = new Query();
            query.addCriteria(Criteria.where("activityQuestionId").is(questionInfo.getId()));
            this.mongoTemplate.remove(query, ActivityAnswerInfo.class);
            this.mongoTemplate.insertAll(questionInfo.getAnswerInfos());

        });
        log.info("导入执行题库完毕- >{}", activityQaInfoId);
    }

    private List<ActivityAnswerInfo> buildImportQaQuestionAnswer(String activityId, String activityQaInfoId, QaQuestionImportVO qaQuestionImport) {
        String questionOption_1 = qaQuestionImport.getQuestionOption_1();
        String questionOption_2 = qaQuestionImport.getQuestionOption_2();
        String questionOption_3 = qaQuestionImport.getQuestionOption_3();
        String questionOption_4 = qaQuestionImport.getQuestionOption_4();
        List<ActivityAnswerInfo> answerInfoList = new ArrayList<>();
        String questionAnswer[] = qaQuestionImport.getAnswer().split(",");
        if (StringUtils.isNotBlank(questionOption_1)) {
            answerInfoList.add(buildAnswer(activityId, activityQaInfoId, 1, questionOption_1, questionAnswer));
        }
        if (StringUtils.isNotBlank(questionOption_2)) {
            answerInfoList.add(buildAnswer(activityId, activityQaInfoId, 2, questionOption_2, questionAnswer));
        }
        if (StringUtils.isNotBlank(questionOption_3)) {
            answerInfoList.add(buildAnswer(activityId, activityQaInfoId, 3, questionOption_3, questionAnswer));
        }
        if (StringUtils.isNotBlank(questionOption_4)) {
            answerInfoList.add(buildAnswer(activityId, activityQaInfoId, 4, questionOption_4, questionAnswer));
        }
        log.info("题库->{}", JSON.toJSONString(answerInfoList));
        return answerInfoList;
    }

    private ActivityAnswerInfo buildAnswer(String activityId, String activityQaInfoId,
                                           Integer answerNumber, String questionOption,
                                           String[] questionAnswer) {
        ActivityAnswerInfo activityAnswerInfo = new ActivityAnswerInfo();
        activityAnswerInfo.setActivityQuestionId(activityQaInfoId);
        activityAnswerInfo.setActivityId(activityId);
        activityAnswerInfo.setPriority(1);
        activityAnswerInfo.setId(null);
        activityAnswerInfo.setTitle(questionOption);
        long count = Arrays.stream(questionAnswer).filter(answerInfo -> Integer.valueOf(answerInfo) == answerNumber).count();
        if (count > 0) {
            activityAnswerInfo.setAnswered(Boolean.TRUE);
        }
        return activityAnswerInfo;
    }


    private void checkQaQuestion(String activityQaInfoId, QaQuestionImportVO qaQuestionImport) {
        Integer type = qaQuestionImport.getType();
        String answers = qaQuestionImport.getAnswer();
        if (StringUtils.isBlank(answers)) {
            log.error("题编号 - > {} 答案不能为空", activityQaInfoId);
            throw new BusinessException("答案不能为空");
        }
        String[] answerSplit = answers.split(",");
        if (type == 2) {
            if (answerSplit.length == 1) {
                log.error("题编号 - > {} 多选题类型和答案不符合", activityQaInfoId);
                throw new BusinessException("多选题类型和答案不符合");
            }
        } else {
            if (answerSplit.length > 1) {
                log.error("题编号 - > {} 单选类型和答案不符合", activityQaInfoId);
                throw new BusinessException("单选题类型和答案不符合");
            }
        }
        if (qaQuestionImport.getScore() == 0D) {
            log.error("题编号 - > {} 分数为0", qaQuestionImport.getQaQuestionNumber());
            throw new BusinessException("分数未设置0");
        }
        String title = qaQuestionImport.getTitle();
        if (StringUtils.isBlank(title)) {
            log.error("题编号 - > {} 问题名称为空", qaQuestionImport.getQaQuestionNumber());
            throw new BusinessException("问题名称不能为空");
        }


    }

    @Override
    public Page<ActivityQaInfo> list(ActivityQaInfoQueryVO req) {
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").ne(true));
        if (Objects.nonNull(req.getStatus())) {
            query.addCriteria(Criteria.where("status").is(req.getStatus()));
        }
        if (StringUtils.isNotBlank(req.getName())) {
            Pattern pattern = Pattern.compile("^.*" + req.getName() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("name").regex(pattern));
        }
        if (StringUtils.isNotBlank(req.getActivityId())) {
            query.addCriteria(Criteria.where("activityId").is(req.getActivityId()));
        }
        req.setPageSize(50);
        long count = mongoTemplate.count(query, ActivityQaInfo.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "createdTime"));
        Sort sort = Sort.by(Sort.Direction.DESC, "createdTime");
        query.with(sort);
        List<ActivityQaInfo> infos1 = mongoTemplate.find(query.with(pageRequest), ActivityQaInfo.class);
        for (ActivityQaInfo activityQaInfo : infos1) {
            if (StringUtils.isBlank(activityQaInfo.getActivityId())) {
                continue;
            }
            Query query1 = new Query().addCriteria(Criteria.where("id").is(activityQaInfo.getActivityId()));
            ActivityInfo activityInfo = mongoTemplate.findOne(query1, ActivityInfo.class);
            activityQaInfo.setActivityName(activityInfo == null ? "" : activityInfo.getName());
        }
        return PageableExecutionUtils.getPage(infos1, pageRequest, () -> count);
    }

    @Override
    public boolean create(ActivityQaInfo req) {
        log.info(":>>> 开始创建问卷:{}", JSON.toJSON(req));
        Date date = new Date();
        if (Objects.isNull(req) || StringUtils.isBlank(req.getImageUr()) || StringUtils.isBlank(req.getName()) || StringUtils.isBlank(req.getDesc()) || StringUtils.isBlank(req.getDetail())) {
            log.error(":>>> 创建题目参数错误");
            throw new BusinessException("创建题目参de数错误:名字、描述、详情、总分数不能为空");
        }
        if (StringUtils.isNotBlank(req.getActivityId())) {
            ActivityInfo activityInfo = activityService.findOne(req.getActivityId());
            req.setActivityName(activityInfo == null ? null : activityInfo.getName());
        }
        req.setCreatedTime(date);
        req = mongoTemplate.insert(req);
        return true;
    }

    @Override
    public boolean update(ActivityQaInfo req) {
        log.info(":>>> 开始修改问卷:{}", JSON.toJSON(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 修改问卷参数错误");
            throw new BusinessException("修改问卷参数错误:Id不能为空");
        }
        Date date = new Date();
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getName())) {
            update.set("name", req.getName());
        }
        if (StringUtils.isNotBlank(req.getImageUr())) {
            update.set("imageUr", req.getImageUr());
        }
        if (StringUtils.isNotBlank(req.getDesc())) {
            update.set("desc", req.getDesc());
        }
        if (StringUtils.isNotBlank(req.getDetail())) {
            update.set("detail", req.getDetail());
        }
        if (Objects.nonNull(req.getScore())) {
            update.set("score", req.getScore());
        }
        if (Objects.nonNull(req.getStatus())) {
            update.set("status", req.getStatus());
        }
        if (StringUtils.isNotBlank(req.getActivityId())) {
            update.set("activityId", req.getActivityId());
            ActivityInfo activityInfo = activityService.findOne(req.getActivityId());
            req.setActivityName(activityInfo == null ? null : activityInfo.getName());
            update.set("activityName", req.getActivityName());

        }
        if (StringUtils.isNotBlank(req.getContestName())) {
            update.set("contestName", req.getContestName());
        }
        if (Objects.nonNull(req.getNo())) {
            update.set("no", req.getNo());
        }
        if (Objects.nonNull(req.getLimitTime())) {
            update.set("limitTime", req.getLimitTime());
        }
        if (Objects.nonNull(req.getLimitTimed())) {
            update.set("limitTimed", req.getLimitTimed());
        }
        if (Objects.nonNull(req.getPassQaScore())) {
            update.set("passQaScore", req.getPassQaScore());
        }
        if (Objects.nonNull(req.getTotalQaNum())) {
            update.set("totalQaNum", req.getTotalQaNum());
        }
        if (Objects.nonNull(req.getButtonStatus())) {
            update.set("buttonStatus", req.getButtonStatus());
        }
        if (Objects.nonNull(req.getNextQaName())) {
            update.set("nextQaName", req.getNextQaName());
        }
        if (Objects.nonNull(req.getQaAccumulation())) {
            update.set("qaAccumulation", req.getQaAccumulation());
        }
        Boolean randomQa = req.getRandomQa();
        Integer randomMultiQaCount = req.getRandomMultiQaCount();
        Integer randomRadioQaCount = req.getRandomRadioQaCount();
        update.set("qaSystemNumber", req.getQaSystemNumber());
        update.set("randomQa", randomQa);
        update.set("randomRadioQaCount", randomRadioQaCount);
        update.set("randomMultiQaCount", randomMultiQaCount);
        update.set("qaLimitTime", req.getQaLimitTime());
        update.set("updatedTime", date);
        update.set("qaLockImageUrl", req.getQaLockImageUrl());
        update.set("qaUnLockImageUrl", req.getQaUnLockImageUrl());
        update.set("qaChannel", req.getQaChannel());
        update.set("outerQaLinker", req.getOuterQaLinker());
        update.set("mediaType", req.getMediaType());
        update.set("mediaUrl", req.getMediaUrl());
        update.set("mediaDesc", req.getMediaDesc());
        mongoTemplate.updateFirst(query, update, ActivityQaInfo.class);
        return true;
    }

    @Override
    public boolean delete(String tenantId, String id) {
        log.info(":>>> 开始删除问卷:{},{}", tenantId, id);
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityQaInfo activityQaInfo = mongoTemplate.findOne(query, ActivityQaInfo.class);
        if (Objects.isNull(activityQaInfo)) {
            log.error(":>>> 题库:{} 不存在", id);
            throw new BusinessException("题库不存在");
        }
        if (StringUtils.isNotBlank(activityQaInfo.getActivityId())) {
            log.error(":>>> 题库:{} 已经被活动:{} 使用,不能删除", id, activityQaInfo.getActivityId());
            throw new BusinessException("题库已经被活动使用");
        }
        Update update = new Update();
        update.set("deleted", true);
        update.set("updatedTime", new Date());
        UpdateResult deleteResult = mongoTemplate.updateFirst(query, update, ActivityQaInfo.class);
        return deleteResult.getModifiedCount() > 0 ? true : false;
    }

    @Override
    public ActivityQaInfo findOne(String id) {
        log.info(":>>> 开始查询问卷:{}", id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 查询题目参数错误:ID为空");
            throw new BusinessException("查询题目参数错误:ID为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityQaInfo activityQaInfo = mongoTemplate.findOne(query, ActivityQaInfo.class);
        log.info(":>>> 题库:{},{}", id, JSON.toJSONString(activityQaInfo));
        if (Objects.nonNull(activityQaInfo)) {
            ActivityInfo activityInfo = activityService.findOne(activityQaInfo.getActivityId());
            if (Objects.nonNull(activityInfo)) {
                Long dianZanNum = this.getJoinNum(activityInfo.getId(), activityInfo.getInitJoinNum(), true);
                Long randomViewNum = this.getViewNum(activityInfo.getId(), activityInfo.getInitJoinNum(), true);
                activityQaInfo.setBrowseNum(randomViewNum.intValue());
                activityQaInfo.setDianZanNum(dianZanNum.intValue());
            }
        }
        return activityQaInfo;
    }

    @Override
    public Page<ActivityQuestionInfo> listQuestion(ActivityQaQuestionQueryVO req) {
        log.info(":>>> 问题列表:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getActivityQaInfoId())) {
            log.error(":>>> 问题列表参数错误:题库ID不能为空");
            throw new BusinessException("题库ID不能为空");
        }
        //req.setPageSize(50);
        Query query = new Query();
        query.addCriteria(Criteria.where("deleted").ne(true));
        if (StringUtils.isNotBlank(req.getActivityQaInfoId())) {
            query.addCriteria(Criteria.where("activityQaInfoId").is(req.getActivityQaInfoId()));
        }
        if (StringUtils.isNotBlank(req.getTitle())) {
            Pattern pattern = Pattern.compile("^.*" + req.getTitle() + ".*$", Pattern.CASE_INSENSITIVE);
            query.addCriteria(Criteria.where("title").regex(pattern));
        }
        long count = mongoTemplate.count(query, ActivityQuestionInfo.class);
        PageRequest pageRequest = PageRequest.of(req.getPage() - 1, req.getPageSize());
//        query.with(new Sort(Sort.Direction.DESC, "priority"));
        Sort sort = Sort.by(Sort.Direction.DESC, "priority");
        query.with(sort);
        List<ActivityQuestionInfo> infos1 = mongoTemplate.find(query.with(pageRequest), ActivityQuestionInfo.class);
        if (CollectionUtils.isNotEmpty(infos1)) {
            for (ActivityQuestionInfo questionInfo : infos1) {
                Query query1 = new Query().addCriteria(Criteria.where("activityQuestionId").is(questionInfo.getId()));
//                query1.with(new Sort(Sort.Direction.DESC, "priority"));
                Sort sort1 = Sort.by(Sort.Direction.DESC, "priority");
                query1.with(sort1);
                List<ActivityAnswerInfo> answerInfos = mongoTemplate.find(query1, ActivityAnswerInfo.class);
                questionInfo.setAnswerInfos(answerInfos);
            }
        }
        return PageableExecutionUtils.getPage(infos1, pageRequest, () -> count);
    }

    @Override
    public boolean createQuestion(ActivityQuestionInfo req) {
        log.info(":>>> 开始新增问题:{}", JSON.toJSONString(req));
        Date date = new Date();
        if (StringUtils.isBlank(req.getActivityQaInfoId()) || StringUtils.isBlank(req.getTitle()) || Objects.isNull(req.getScore()) || Objects.isNull(req.getType()) || Objects.isNull(req.getPriority()) ||
                CollectionUtils.isEmpty(req.getAnswerInfos())) {
            log.error(":>>> 创建题目参数错误:题目、分数、类型、排序、答案不能为空");
            throw new BusinessException("创建题目参数错误:题目、分数、类型、排序、答案不能为空");
        }
        req.setId(null);
        req.setCreatedTime(new Date());
        if (StringUtils.isNotBlank(req.getId())) {
            mongoTemplate.save(req);
        } else {
            req = mongoTemplate.insert(req);
        }
        for (ActivityAnswerInfo answerInfo : req.getAnswerInfos()) {
            if (StringUtils.isBlank(answerInfo.getTitle()) || Objects.isNull(answerInfo.getAnswered()) || Objects.isNull(answerInfo.getPriority())) {
                log.error(":>>> 创建题目参数错误:答案题目、是否是排序不能为空");
                throw new BusinessException("创建题目参数错误:答案题目、是否是排序不能为空");
            }
            answerInfo.setCreatedTime(date);
            answerInfo.setActivityQuestionId(req.getId());
            answerInfo.setId(null);
        }
        mongoTemplate.insertAll(req.getAnswerInfos());
        return true;
    }

    @Override
    public boolean updateQuestion(ActivityQuestionInfo req) {
        log.info(":>>> 开始修改问题:{}", JSON.toJSONString(req));
        if (Objects.isNull(req) || StringUtils.isBlank(req.getId())) {
            log.error(":>>> 修改问卷题目参数错误:ID不能为空");
            throw new BusinessException("修改问卷题目参数错误:ID不能为空");
        }
        Date date = new Date();
        Query query = new Query().addCriteria(Criteria.where("id").is(req.getId()));
        Update update = new Update();
        if (StringUtils.isNotBlank(req.getTitle())) {
            update.set("title", req.getTitle());
        }
        if (Objects.nonNull(req.getPriority())) {
            update.set("priority", req.getPriority());
        }
        if (Objects.nonNull(req.getScore())) {
            update.set("score", req.getScore());
        }
        if (Objects.nonNull(req.getType())) {
            update.set("type", req.getType());
        }
        if (StringUtils.isNotBlank(req.getQaAnalysis())) {
            update.set("qaAnalysis", req.getQaAnalysis());
        }

        update.set("updatedTime", date);
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, ActivityQuestionInfo.class);
        log.info(":>>> 更新问题:{},结果为:{}", req.getId(), updateResult.getModifiedCount() > 0 ? true : false);
        if (CollectionUtils.isNotEmpty(req.getAnswerInfos())) {
            List<String> removeIds = new ArrayList<>();
            for (ActivityAnswerInfo answerInfo : req.getAnswerInfos()) {
                if (StringUtils.isNotBlank(answerInfo.getId())) {
                    Query query1 = new Query().addCriteria(Criteria.where("id").is(answerInfo.getId()));
                    Update updat1 = new Update();

                    if (StringUtils.isNotBlank(answerInfo.getTitle())) {
                        updat1.set("title", answerInfo.getTitle());
                    }
                    if (Objects.nonNull(answerInfo.getAnswered())) {
                        updat1.set("answered", answerInfo.getAnswered());
                    }
                    if (Objects.nonNull(answerInfo.getPriority())) {
                        updat1.set("priority", answerInfo.getPriority());
                    }
                    mongoTemplate.updateFirst(query1, updat1, ActivityAnswerInfo.class);
                    removeIds.add(answerInfo.getId());
                } else {
                    answerInfo.setId(null);
                    answerInfo.setCreatedTime(new Date());
                    answerInfo.setActivityQuestionId(req.getId());
                    answerInfo = mongoTemplate.insert(answerInfo);
                    removeIds.add(answerInfo.getId());
                }
            }
            if (CollectionUtils.isNotEmpty(removeIds)) {
                Query queryRemove = new Query().addCriteria(Criteria.where("id").nin(removeIds).and("activityQuestionId").is(req.getId()));
                DeleteResult deleteResult = mongoTemplate.remove(queryRemove, ActivityAnswerInfo.class);
                log.info(":>>> 删除的数量为:{}", deleteResult.getDeletedCount());
            }
        }

        return true;
    }

    @Override
    public boolean deleteQuestion(String tenantId, String id) {
        log.info(":>>> 开始删除问题:{}", id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 删除问题错误:ID 为空");
            throw new BusinessException("删除问题错误:ID 为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        Query query1 = new Query().addCriteria(Criteria.where("activityQuestionId").is(id));
        mongoTemplate.remove(query1, ActivityAnswerInfo.class);
        mongoTemplate.remove(query, ActivityQuestionInfo.class);
        return true;
    }

    @Override
    public ActivityQuestionInfo findOneQuestion(String tenantId, String id) {
        log.info(":>>> 开始查找问题:{}", id);
        if (StringUtils.isBlank(id)) {
            log.error(":>>> 获取问题错误:ID 为空");
            throw new BusinessException("获取问题错误:ID 为空");
        }
        Query query = new Query().addCriteria(Criteria.where("id").is(id));
        ActivityQuestionInfo info = mongoTemplate.findOne(query, ActivityQuestionInfo.class);
        if (Objects.nonNull(info)) {
            Query query1 = new Query().addCriteria(Criteria.where("activityQuestionId").is(info.getId()));
//            query.with(new Sort(Sort.Direction.DESC, "priority"));
            Sort sort = Sort.by(Sort.Direction.DESC, "priority");
            query.with(sort);
            List<ActivityAnswerInfo> answerInfos = mongoTemplate.find(query1, ActivityAnswerInfo.class);
            info.setAnswerInfos(answerInfos);
        }
        return info;
    }

    @Override
    public List<ActivityQaInfo> findByActivityId(String activityId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return this.mongoTemplate.find(query, ActivityQaInfo.class);
    }

    @Override
    public ActivityQaInfo findByActivityIdAndQaNumber(String activityId, Integer qaNumber) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(activityId));
        query.addCriteria(Criteria.where("no").is(qaNumber));
        return this.mongoTemplate.findOne(query, ActivityQaInfo.class);
    }

    @Override
    public UserQaInfoResponse getQaInfo(QaInfoReq qaInfoReq) {
        String activityId = qaInfoReq.getActivityId();
        String qaInfoId = qaInfoReq.getQaInfoId();
        UserPO currentUser = qaInfoReq.getCurrentUser();
        Integer pageNo = qaInfoReq.getPageNo();
        Integer pageSize = qaInfoReq.getPageSize();
        ActivityQaInfo activityQaInfo = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        if (Objects.isNull(activityQaInfo)) {
            throw new BusinessException("答题不存在");
        }
        log.info("用户->{}获取答题->{}信息", currentUser.getId(), qaInfoId);
        if (qaInfoReq.getQaType().equals("1")) {
            //验证答题次数
            if (qaInfoReq.getType() == 1 && activityQaInfo.getNo() != 1) {
                userQaInfoService.checkQaLimit(1, currentUser.getId(), qaInfoId);
            } else {
                userQaInfoService.checkQaLimit(2, currentUser.getId(), qaInfoId);
            }
        }

        UserQaInfoResponse userQaInfoResponse = new UserQaInfoResponse();
        userQaInfoResponse.setActivityId(activityId);
        userQaInfoResponse.setActivityName(activityQaInfo.getActivityName());
        userQaInfoResponse.setQaInfoId(qaInfoId);
        userQaInfoResponse.setLimitTimed(activityQaInfo.getLimitTimed());
        userQaInfoResponse.setLimitTime(activityQaInfo.getLimitTime());
        userQaInfoResponse.setQaType("QA");
        userQaInfoResponse.setQaSystemNumber(activityQaInfo.getQaSystemNumber());
        userQaInfoResponse.setQaLimitTime(activityQaInfo.getQaLimitTime());
        if (!qaInfoReq.getQaType().equals("2")) {
            UserQuestionInfo userQuestionInfo = getUserQuestionInfo(activityId, currentUser, qaInfoId);
            if (Objects.nonNull(userQuestionInfo)) {
                int totalSize = userQuestionInfo.getQuestionInfoList().size();
                List<ActivityQuestionInfo> questionInfoList = userQuestionInfo.getQuestionInfoList();
                userQaInfoResponse.setQuestionInfo(competitionQaInfoService.questionInfoPage(pageNo, pageSize, totalSize,
                        questionInfoList));
                return userQaInfoResponse;
            }
        }
        //题库练习用于不随机
        if (qaInfoReq.getQaType().equals("2")) {
            activityQaInfo.setRandomQa(Boolean.FALSE);
        }
        List<ActivityQuestionInfo> qaList = getActivityQuestionInfos(qaInfoId);
        competitionQaInfoService.qaBuild(pageNo, pageSize, currentUser, activityQaInfo, qaList, userQaInfoResponse);
        return userQaInfoResponse;
    }

    private List<ActivityQuestionInfo> getActivityQuestionInfos(String qaInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.with(Sort.by(Sort.Direction.ASC, "priority"));
        return this.mongoTemplate.find(query, ActivityQuestionInfo.class);
    }

    @Override
    public UserQaInfoResponse getH5PlusQaInfo(QaInfoReq qaInfoReq) {
        String activityId = qaInfoReq.getActivityId();
        UserPO currentUser = qaInfoReq.getCurrentUser();
        String qaInfoId = qaInfoReq.getQaInfoId();
        String userId = currentUser.getId();
        log.info("【题库信息】activityId ->{}  qaInfoId -> {} userId-> {}", activityId, qaInfoId, userId);
        Integer pageNo = qaInfoReq.getPageNo();
        Integer pageSize = qaInfoReq.getPageSize();
        userQaInfoService.checkQaLimit(2, userId, qaInfoId);
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(userId));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        Update update = new Update();
        update.set("userId", userId + "delete");
        update.set("activityQaInfoId", qaInfoId + "delete");
        update.set("activityId", activityId + "delete");
        this.mongoTemplate.updateMulti(query, update, UserQuestionInfo.class);
        this.mongoTemplate.remove(query, UserQuestionInfo.class);
        ActivityQaInfo qaInfoA = this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
        if (Objects.isNull(qaInfoA)) {
            throw new BusinessException("该题库信息不存在");
        }
        UserQaInfoResponse userQaInfoResponse = new UserQaInfoResponse();
        userQaInfoResponse.setActivityId(activityId);
        userQaInfoResponse.setActivityName(qaInfoA.getActivityName());
        userQaInfoResponse.setQaInfoId(qaInfoId);
        userQaInfoResponse.setLimitTime(qaInfoA.getLimitTime());
        userQaInfoResponse.setLimitTimed(qaInfoA.getLimitTimed());
        userQaInfoResponse.setQaType("QA");
        userQaInfoResponse.setQaLimitTime(qaInfoA.getQaLimitTime());
        userQaInfoResponse.setQaSystemNumber(qaInfoA.getQaSystemNumber());
        UserQuestionInfo userQuestionInfo = getUserQuestionInfo(activityId, currentUser, qaInfoId);
        if (Objects.nonNull(userQuestionInfo)) {
            int totalSize = userQuestionInfo.getQuestionInfoList().size();
            List<ActivityQuestionInfo> questionInfoList = userQuestionInfo.getQuestionInfoList();
            userQaInfoResponse.setQuestionInfo(competitionQaInfoService.questionInfoPage(pageNo, pageSize, totalSize,
                    questionInfoList));
            return userQaInfoResponse;
        }
        log.info("【获取题信息】qaInfoId - > {}", qaInfoId);
        List<ActivityQuestionInfo> randomList = Lists.newLinkedList();
        List<ActivityQuestionInfo> qaListA = getActivityQuestionInfos(qaInfoId);
        userQaInfoResponse.setType(1);
        competitionQaInfoService.qaBuild(pageNo, 10000, currentUser, qaInfoA, qaListA, userQaInfoResponse);
        randomList.addAll(userQaInfoResponse.getQuestionInfo().getContent());
        ActivityQaInfo qaInfoB = this.findByActivityIdAndQaNumber(activityId, 2);
        if (Objects.nonNull(qaInfoB)) {
            List<ActivityQuestionInfo> qaListB = getActivityQuestionInfos(qaInfoB.getId());
            if (CollectionUtils.isNotEmpty(qaListB)) {
                userQaInfoResponse.setQuestionInfo(null);
                userQaInfoResponse.setType(1);
                competitionQaInfoService.qaBuild(pageNo, 10000, currentUser, qaInfoB, qaListB, userQaInfoResponse);
                randomList.addAll(userQaInfoResponse.getQuestionInfo().getContent());
                userQaInfoResponse.setQuestionInfo(null);
            }
        }
        userQaInfoResponse.setType(2);
        Collections.shuffle(randomList);
        userQuestionInfo = new UserQuestionInfo();
        userQuestionInfo.setUserId(currentUser.getId());
        userQuestionInfo.setQuestionInfoList(randomList);
        userQuestionInfo.setActivityQaInfoId(qaInfoId);
        userQuestionInfo.setActivityId(activityId);
        userQuestionInfo.setActivityGroupId(activityId);
        this.mongoTemplate.save(userQuestionInfo);
        userQaInfoResponse.setQuestionInfo(competitionQaInfoService.questionInfoPage(pageNo, pageSize, randomList.size(), randomList));
        //competitionQaInfoService.qaBuild(pageNo,pageSize,currentUser,qaInfoA,randomList, userQaInfoResponse);
        return userQaInfoResponse;
    }

    @Override
    public ActivityQaInfo findById(String qaInfoId) {
        return this.mongoTemplate.findById(qaInfoId, ActivityQaInfo.class);
    }

    @Async
    @Override
    public void doCopyQaInfo(String copySourceActivityId, String newTargetActivityId, String activityName) {
        log.info("【copy 活动题库信息】开始复制活动题库信息 sourceActivityId->{} | newTargetActivityId->{}", copySourceActivityId, newTargetActivityId);
        Query query = new Query();
        query.addCriteria(Criteria.where("activityId").is(copySourceActivityId));
        List<ActivityQaInfo> qaInfoList = this.mongoTemplate.find(query, ActivityQaInfo.class);
        if (CollectionUtils.isEmpty(qaInfoList)) {
            log.error("【copy 活动题库信息】未查询找到复制活动题库信息 sourceActivityId->{} | newTargetActivityId->{}", copySourceActivityId, newTargetActivityId);
            return;
        }
        Date now = new Date();
        List<ActivityQaInfo> targetInfoList = qaInfoList.stream().peek(activityQaInfo -> {
            String oldActivityQaInfoId = activityQaInfo.getId();
            activityQaInfo.setId(ObjectId.get().toString());
            activityQaInfo.setActivityId(newTargetActivityId);
            activityQaInfo.setActivityName(activityName);
            activityQaInfo.setCreatedTime(now);
            activityQaInfo.setUpdatedTime(now);
            CopyActivityQaRuleReq copyActivityQaRuleReq = new CopyActivityQaRuleReq();
            copyActivityQaRuleReq.setCopyActivityId(copySourceActivityId);
            copyActivityQaRuleReq.setTargetCopyActivityId(newTargetActivityId);
            copyActivityQaRuleReq.setCopyActivityQaInfoId(oldActivityQaInfoId);
            copyActivityQaRuleReq.setTargetActivityQaInfoId(activityQaInfo.getId());
            activityQaRuleService.doCopyQaRule(copyActivityQaRuleReq);
        }).collect(Collectors.toList());
        this.mongoTemplate.insertAll(targetInfoList);
        log.info("【copy 活动题库信息】结束复制活动题库信息 sourceActivityId->{} | newTargetActivityId->{}", copySourceActivityId, newTargetActivityId);
    }

    private UserQuestionInfo getUserQuestionInfo(String activityId, UserPO currentUser, String qaInfoId) {
        Query query = new Query();
        query.addCriteria(Criteria.where("userId").is(currentUser.getId()));
        query.addCriteria(Criteria.where("activityQaInfoId").is(qaInfoId));
        query.addCriteria(Criteria.where("activityId").is(activityId));
        return this.mongoTemplate.findOne(query, UserQuestionInfo.class);
    }

    public Long getJoinNum(String activityId, Long initJoinNum, boolean query) {
        if (query) {
            Long total = initJoinNum;
            total += userParticipateActivityInfoService.getJoinedCount(activityId);
            total += userActivityService.getActivityRandomNum(activityId);
            return total;
        }
        return 0L;
    }

    /**
     * 获取视频观看数量
     *
     * @param activityId
     * @param initJoinNum
     * @param query
     * @return
     */
    public Long getViewNum(String activityId, Long initJoinNum, boolean query) {
        if (query) {
            Long total = initJoinNum;
            total += userParticipateActivityInfoService.getJoinedCount(activityId);
            total += userActivityService.getActivityViewRandomNum(activityId);
            return total;
        }
        return 0L;
    }

}
